import { api } from '@T2/plugins/env-config.ts';

interface TreeNode {
  id: number;
  key?: string;
  children?: TreeNode[];
  [key: string]: any; // 允许任意数量的其他属性
}
interface MenuType {
  id: number;
  menu: number | null;
  menu__path: string | null;
  children?: MenuType[];
}
/* 将对象数组 A 中的每个对象根据其 xxx 属性放到对象数组 B 中对应 id 对象的 children 里*/
export const distributeAIntoB = (
  A: TreeNode[],
  B: TreeNode[],
  propName: string
): { updatedB: TreeNode[]; unmatchedA: TreeNode[] } => {
  const bMap: { [key: number]: TreeNode } = {};
  const unmatchedA: TreeNode[] = [];

  // 初始化 B 中的每个对象，并确保每个对象都有 children 属性
  B.forEach(bItem => {
    bMap[bItem.id] = bItem;
    bItem.children = bItem.children || [];
  });

  // 将 A 中的每个对象分配到 B 中对应的对象的 children 数组中
  A.forEach(aItem => {
    const namePro = aItem[propName];
    if (namePro && bMap[namePro]){
      bMap[namePro].children!.push(aItem);
    } else {
      unmatchedA.push(aItem);
    }
  });

  return { updatedB: B, unmatchedA };
}

/* 树状结构 */
export const buildTree = (lists: any[], str: string) => {
  /* str 表示父级id对应的字段名 */
  let treeMap: any = {}, tree: any = [];
  lists?.forEach(item => {
    let obj = treeMap[item.id];
    treeMap[item.id] = {
      ...item,
      children: obj?.children || item.children || [],
    }
    if (item[str]) {
      if (!treeMap[item[str]]) {
        treeMap[item[str]] = {children: []};
      }
      treeMap[item[str]].children.push(treeMap[item.id]);
    } else {
      tree.push(treeMap[item.id]);
    }
  });
  return tree
}
export const buildPositionUnitTree = (units: any[], position: any[], positionDisabled: boolean) : TreeNode[] => {
  const tree : TreeNode[] = [];
  // if (!position.length) {
  //   return tree;
  // }
  /* 构建 position 的节点映射 */
  const positionNode: { [key: string]: any } = {};
  position.forEach((pos: any) => {
    pos.children = [];
    pos.disabled = positionDisabled;
    positionNode[pos.id] = pos;
  });
  
  /* 将 units 添加到对应的 position 节点下 */
  const lonlyUnit: TreeNode[] = [];
  units.forEach((unit: any) => {
    unit.key = unit.id + 'unit';
    const posId = unit.positon;
    if (posId && positionNode[posId]) {
      positionNode[posId].children.push(unit);
    } else {
      lonlyUnit.push(unit);
    }
  });
  
  /* positon为null的push到tree里去 */
  tree.push(...lonlyUnit);
  
  /* 构建树状结构 */
  position.forEach((pos: any) => {
    pos.key = pos.id + 'position';
    if (pos.parent && positionNode[pos.parent]) {
      positionNode[pos.parent].children.push(positionNode[pos.id]);
    } else {
      tree.push(positionNode[pos.id]);
    }
  });
  
  /* 遍历树状结构，剔除末端unit对象不包含 position 属性的链条 */
  // const pruneTree = (node: TreeNode) => {
  //   if (node.hasOwnProperty('positon')) {
  //     return node;
  //   }
  //   const children = node.children?.map(pruneTree).filter((child: TreeNode | null) => child !== null);
  //   if (children?.length) {
  //     return { ...node, children };
  //   }
  //   return null;
  // };
  // return tree.map(pruneTree).filter((node) => node !== null) as TreeNode[];
  
  return tree as TreeNode[];
}

/* 根据某个属性的值查找树状结构中对应的对象 */
export const findNodeByProperty = (nodes: TreeNode[], propName: 'id' | 'key', propValue: any): TreeNode | undefined => {
  for (const node of nodes) {
    if (node[propName] === propValue) {
      return node; // 如果当前节点的属性值满足条件，则返回当前节点
    }
    if (node.children) {
      const result = findNodeByProperty(node.children, propName, propValue);
      if (result) {
        return result; // 如果在子树中找到满足条件的节点，则返回找到的节点
      }
    }
  }
  return undefined; // 如果在当前子树中未找到满足条件的节点，则返回 undefined
}
/* 查找树状结构中匹配到某个对象后，返回根节点对象 */
export const findNodeRoot = (tree: TreeNode[], attr: string, value: any): TreeNode | null => {
  const searchNode = (node: TreeNode, root: TreeNode): TreeNode | null => {
    if (node[attr] === value) {
      return root;
    }
    if (node.children) {
      for (const child of node.children) {
        const result = searchNode(child, root);
        if (result) {
          return result;
        }
      }
    }
    return null;
  }
  for (const root of tree) {
    const result = searchNode(root, root);
    if (result) {
      return result;
    }
  }
  return null;
}

interface AttrNode {
  id?: number;
  name: string;
  key?: string;
  children?: AttrNode[];
  [key: string]: any;
}
export const setTreeByAttr = (data: AttrNode[], attr: string): AttrNode[] => {
  const map = new Map<string, AttrNode>();

  data.forEach((item, index) => {
    item.key = item.id + '';
    const name = item[attr];
    if (!map.has(name)) {
      map.set(name, { name: name, key: index + attr, children: [] });
    }
    map.get(name)!.children!.push(item);
  });

  return Array.from(map.values());
}

/* 判断是否是有效手机号 */
export const isPhone = (num: string) => {
  if (!num || num.length < 11) {
    return false;
  }

  if (!/^1\d{10}/.test(num)) {
    return false;
  }
  let req = /1[3456789]\d{9}$/;
  if (!req.test(num)) {
    return false;
  }
  return true;
}

/* 深拷贝对象/数组 */
export const deepCopy = <T>(obj: Readonly<T>): T => {
  if (Array.isArray(obj)) {
    const copiedArray: any[] = [];
    for (const item of obj) {
      copiedArray.push(deepCopy(item));
    }
    return copiedArray as T;
  } else if (typeof obj === 'object' && obj !== null) {
    const copiedObj: any = {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        copiedObj[key] = deepCopy(obj[key]!);
      }
    }
    return copiedObj as T;
  } else {
    return obj;
  }
}

/* 筛选菜单 */
interface MenuNode {
  used: boolean;
  children?: MenuNode[];
  roles?: number[];
  [key: string]: any;
}
/* 筛选已开放的菜单 */
export const getUsedMenus = (menus: MenuNode[]): MenuNode[] => {
  const pruneTree = (node: MenuNode): MenuNode | null => {
    /* 剔除不包含的菜单以及不包含的功能权限 */
    if (!node.used) {
      /* 关闭的菜单直接剔除 */
      return null;
    }
    const leaf = node.children?.length ? false : true;
    const children = (node.children?.map(pruneTree).filter(child => child !== null) || []) as MenuNode[];
    if (children?.length) {
      /* 非叶子节点则返回过滤后的node */
      return { ...node, children };
    }
    if (leaf && node.menu) {
      /* 叶子节点则返回过滤后的node */
      return { ...node, children };
    }
    return null;
  }
  return (menus.map(pruneTree).filter((node) => node !== null) || []) as MenuNode[];
}
interface Role {
  id: number;
  [key: string]: any;
}
/* 筛选已开放并且有权限的菜单 */
export const getValidMenus = (menus: MenuNode[], isSuper: boolean, roles: Role[]): MenuNode[] => {
  const pruneTree = (node: MenuNode): MenuNode | null => {
    /* 剔除不包含的菜单以及不包含的功能权限 */
    if (!node.used) {
      /* 关闭的菜单直接剔除 */
      return null;
    }
    const leaf = node.children?.length ? false : true;
    const children = (node.children?.map(pruneTree).filter(child => child !== null) || []) as MenuNode[];
    if (children?.length) {
      /* 非叶子节点则返回过滤后的node */
      return { ...node, children };
    }
    if (leaf && node.menu && (isSuper || (node.roles?.length && roles.some(item => node.roles!.includes(item.id))))) {
      /* 叶子节点则返回过滤后的node */
      return { ...node, children };
    }
    return null;
  }
  
  return (menus.map(pruneTree).filter((node) => node !== null) || []) as MenuNode[];
}

export const downloadFiles = (name: string, url: string): void => {
  // 创建一个隐藏的<a>元素
  const link = document.createElement('a');
  link.href = api + url;
  link.style.display = 'none';
  // 设置下载文件名，如果有的话
  if (name) {
    link.setAttribute('download', name);
  }
  // 将<a>元素添加到页面中
  document.body.appendChild(link);
  // 模拟点击<a>元素进行下载
  link.click();
  // 清理添加的<a>元素
  document.body.removeChild(link);
}

export const downloadFiles2 = (name: string, url: string): void=> {
  console.log('开始下载文件...', name, url);
  
  fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      return response.blob();
    })
    .then(blob => {
      // 创建 Blob URL
      const objectURL = URL.createObjectURL(blob);
      // 创建隐藏的 <a> 元素
      const link = document.createElement('a');
      link.href = objectURL;
      link.download = name || 'downloaded-file';
      link.style.display = 'none';

      document.body.appendChild(link);
      link.click(); // 模拟点击

      // 清理工作
      document.body.removeChild(link);
      URL.revokeObjectURL(objectURL); // 释放 Blob URL
    })
    .catch(error => {
      console.error('下载失败:', error);
    });
}

/* 判断一个字符串是否可以被 JSON.parse 解析为 JSON */
export const isJSON = (str: string): boolean => {
  try {
    JSON.parse(str);
    return true;
  } catch (e) {
    return false;
  }
}

/* 找出用户已有菜单的跳转路径 */
export const findMenuPath = (menu: MenuType[], str: string): string | null => {
  for (const item of menu) {
    if (item.menu__path?.includes(str)) {
      return item.menu__path;
    }
    if (item.children) {
      const result = findMenuPath(item.children, str);
      if (result) {
        return result;
      }
    }
  }
  return null;
}

/* 防抖 */
export const debounce = <T extends (...args: any[]) => void>(func: T, delay: number): ((...args: Parameters<T>) => void) => {
  let timer: ReturnType<typeof setTimeout>;

  return (...args: Parameters<T>): void => {
    clearTimeout(timer);
    timer = setTimeout(() => func(...args), delay);
  };
};

/* 深度优先搜索DFS */
type Link = Record<string, string>;
export const canConnectNodesDFS = (
  startId: string,
  endIds: string[],
  links: Link[],
  sourceKey: string,
  targetKey: string
): boolean => {
  // 构造邻接表
  const adjacencyList: Record<string, string[]> = {};

  links.forEach((link) => {
    const sourceNodeId = link[sourceKey];
    const targetNodeId = link[targetKey];
    if (!adjacencyList[sourceNodeId]) {
      adjacencyList[sourceNodeId] = [];
    }
    adjacencyList[sourceNodeId].push(targetNodeId);
  });

  // 使用 Set 来存储访问过的节点
  const visited = new Set<string>();
  const paths: string[][] = [];

  // 深度优先搜索，收集所有从 startId 出发的路径
  const dfs = (node: string, currentPath: string[]) => {
    visited.add(node);
    currentPath.push(node);

    // 如果该节点没有邻居，表示路径已结束
    const neighbors = adjacencyList[node] || [];
    if (neighbors.length === 0) {
      paths.push([...currentPath]);
    }

    // 递归遍历邻居节点
    for (const neighbor of neighbors) {
      if (!visited.has(neighbor)) {
        dfs(neighbor, currentPath);
      }
    }

    // 回溯
    currentPath.pop();
    visited.delete(node);
  };

  // 从 startId 开始深度优先搜索
  dfs(startId, []);

  // 1. paths 必须大于 0，2. 每条路径的结束节点必须在 endIds 中
  return (
    paths.length > 0 &&
    paths.every((path) => endIds.includes(path[path.length - 1]))
  );
};
/**
 * 将颜色字符串转换为RGBA格式
 * @param color - 颜色字符串，例如 '#ff5733'、'rgb(255, 87, 51)' 或 'rgba(255, 87, 51, 0.5)'
 * @param alpha - 透明度（0到1之间）
 * @returns RGBA颜色字符串，例如 'rgba(255, 87, 51, 0.5)'
 */
export function colorToRgba(color: string, alpha: number): string {
  /**
   * 将十六进制颜色转换为RGBA格式
   * @param hex - 十六进制颜色，例如 '#ff5733'
   * @param alpha - 透明度（0到1之间）
   * @returns RGBA颜色字符串，例如 'rgba(255, 87, 51, 0.5)'
   */
  function hexToRgba(hex: string, alpha: number): string {
    let c: number;
    if (hex.length === 4) {
      c = parseInt(hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3], 16);
    } else {
      c = parseInt(hex.substring(1), 16);
    }
    const r = (c >> 16) & 255;
    const g = (c >> 8) & 255;
    const b = c & 255;
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  }
  /**
   * 将RGB颜色转换为RGBA格式
   * @param rgb - RGB颜色，例如 'rgb(255, 87, 51)'
   * @param alpha - 透明度（0到1之间）
   * @returns RGBA颜色字符串，例如 'rgba(255, 87, 51, 0.5)'
   */
  function rgbToRgba(rgb: string, alpha: number): string {
    const result = /^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.exec(rgb);
    if (!result) {
      throw new Error('无效的RGB颜色格式');
    }
    const r = parseInt(result[1], 10);
    const g = parseInt(result[2], 10);
    const b = parseInt(result[3], 10);
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  }
  if (typeof color !== 'string') {
    return '#000000';
  }
  // 检查是否为RGBA颜色
  if (/^rgba\((\d{1,3}), (\d{1,3}), (\d{1,3}), ([01]|0?\.\d+)\)$/.test(color)) {
    return color;
  }
  // 检查是否为十六进制颜色
  if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(color)) {
    return hexToRgba(color, alpha);
  }
  // 检查是否为RGB颜色
  if (/^rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)$/.test(color)) {
    return rgbToRgba(color, alpha);
  }
  return '#000000';
}
